#pragma once

#include <iostream>
#include <jsoncpp/json/json.h>
#include <cstdio>
#include <ctime>
#include <random>
#include <atomic>
#include <iomanip>

#define Die(code)   \
    do              \
    {               \
        exit(code); \
    } while (0)

#define CONV(v) (struct sockaddr *)(v)

enum
{
    USAGE_ERR = 1,
    SOCKET_ERR,
    BIND_ERR,
    LISTEN_ERR,
    CONNECT_ERR
};

namespace zj
{
    class JsonAPI
    {
    public:
        static bool serialize(const Json::Value &val, std::string *body) // 序列化
        {
            std::stringstream ss;
            Json::StreamWriterBuilder builder;
            std::unique_ptr<Json::StreamWriter> sw(builder.newStreamWriter());

            sw->write(val, &ss);

            *body = ss.str();
            return true;
        }

        static bool delserialize(Json::Value &val, const std::string &body) // 反序列化
        {
            // 反序列化，根据一个message生成一个Json::Value
            Json::CharReaderBuilder builder;
            Json::String errs; // 用来存储错误信息
            std::unique_ptr<Json::CharReader> sw(builder.newCharReader());

            bool ret = sw->parse(body.c_str(), body.c_str() + body.size(), &val, &errs);
            if (!ret)
            {
                std::cout << "JSON解析失败: " << errs << std::endl;
            }
            return ret;
        }
    };

    class UUID
    { // 生成uuid
    public:
        static std::string uuid()
        {
            std::stringstream ss;
            // 1. 构造一个机器随机数对象
            std::random_device rd;
            // 2. 以机器随机数为种子构造伪随机数对象
            std::mt19937 generator(rd());
            // 3. 构造限定数据范围的对象
            std::uniform_int_distribution<int> distribution(0, 255);
            // 4. 生成8个随机数，按照特定格式组织成为16进制数字字符的字符串
            for (int i = 0; i < 8; i++)
            {
                if (i == 4 || i == 6)
                    ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << distribution(generator);
            }
            ss << "-";
            // 5. 定义一个8字节序号，逐字节组织成为16进制数字字符的字符串
            static std::atomic<size_t> seq(1); //  00 00 00 00 00 00 00 01
            size_t cur = seq.fetch_add(1);
            for (int i = 7; i >= 0; i--)
            {
                if (i == 5)
                    ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << ((cur >> (i * 8)) & 0xFF);
            }
            return ss.str();
        }
    };
}
